package org.groupg.mockdatabyspring.morkdata.service.runnables;

import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import org.apache.commons.io.FileUtils;
import org.groupg.mockdatabyspring.morkdata.model.DBDataFile;

import java.io.File;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CountDownLatch;

/**
 * 消费者内容，消费者主要就是循环生成行来
 * @author Mr.GenG
 */
public class DataFileConsumer implements Runnable {
    private static final Log log = LogFactory.get();

    private final BlockingQueue<File> taskConsumerQueue;

    private final int rowNum;
    private final DBDataFile dbDataFile;

    private final CountDownLatch latch;

    private final int fileNum;
    private final int maxFileNum;

    /**
     * 初始化函数对象方法，用于创建消费者对象
     * @param taskConsumerQueue 消费者的队列内容，主要内容就是生产者生成的文件
     * @param rowNum 每个消费者需要自行处理的行数
     * @param dbDataFile 数据文件的对象实例
     * @param latch 每个消费者都要处理的同步器
     * @param fileNum 第几个消费者
     * @param maxFileNum 总共要处理多少个文件
     */
    public DataFileConsumer(BlockingQueue<File> taskConsumerQueue, int rowNum, DBDataFile dbDataFile, CountDownLatch latch, int fileNum, int maxFileNum) {
        this.taskConsumerQueue = taskConsumerQueue;
        this.rowNum = rowNum;
        this.dbDataFile = dbDataFile;
        this.latch = latch;
        this.fileNum = fileNum;
        this.maxFileNum = maxFileNum;
    }

    /**
     * When an object implementing interface {@code Runnable} is used
     * to create a thread, starting the thread causes the object's
     * {@code run} method to be called in that separately executing
     * thread.
     * <p>
     * The general contract of the method {@code run} is that it may
     * take any action whatsoever.
     *
     * @see Thread#run()
     */
    @Override
    public void run() {

        try {
            File file = taskConsumerQueue.take();
            log.debug("消费者正在处理【{}/{}】文件：{}，本次处理：{}行",fileNum,maxFileNum,file.getName(),rowNum);
            List<String> lines = new LinkedList<>();
            for (int j = 0; j < rowNum; j++) {
                lines.add(this.dbDataFile.getDbTableInfo().getLineString(this.dbDataFile.getFieldSplit()));
            }
            FileUtils.writeLines(file, this.dbDataFile.getCharsetName(), lines, this.dbDataFile.getLineSplit(), true);
        } catch (InterruptedException | IOException e) {
            log.error(e, e.getMessage());
        } finally {
            latch.countDown();
        }
    }
}
